﻿using System;
using System.Windows.Input;

namespace OmniKits.Windows
{
    using Utilities;

    public class DelegateCommand<T> : ICommand
    {
        private Func<T, bool> _CanExecute;
        private Action<T> _Execute;

        public event EventHandler CanExecuteChanged;

        public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
        {
            if (execute == null)
                throw new ArgumentNullException(nameof(execute));

            _Execute = execute;
            _CanExecute = canExecute;
        }

        bool ICommand.CanExecute(object parameter)
        {
            var accept = (parameter == null) ? TypeUtility<T>.IsNullAssignable : (parameter is T);
            if (!accept) return false;

            if (_CanExecute == null)
                return true;

            return _CanExecute((T)parameter);
        }
        public bool CanExecute(object parameter)
            => (this as ICommand).CanExecute(parameter);

        void ICommand.Execute(object parameter)
        {
            if (!(this as ICommand).CanExecute(this))
                throw new ArgumentException();

            _Execute((T)parameter);
        }
        public void Execute(object parameter)
            => (this as ICommand).Execute(parameter);

        protected void FireCanExecuteChanged()
            => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}
